home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************************
- *
- *
- * ObjectMacZapp -- a standard Mac OOP application template
- *
- *
- *
- * ZFile.cpp -- a generic file object
- *
- *
- *
- *
- *
- * © 1996, Graham Cox
- *
- *
- *
- *
- *************************************************************************************************/
-
- #include "ZFile.h"
- #include "MacZoop.h"
-
-
- /*-------------------------------*** CONSTRUCTOR ***----------------------------------*/
-
-
-
- ZFile::ZFile( const FSSpec& aSpec )
- : ZComrade()
- {
- itsSpec = aSpec;
-
- InitFile();
- }
-
-
- /*-------------------------------*** CONSTRUCTOR ***----------------------------------*/
-
- ZFile::ZFile( Str255 fName )
- {
- short vRefNum;
-
- FailOSErr( GetVol( NULL, &vRefNum ));
- FailOSErr( FSMakeFSSpec( vRefNum, 0, fName, &itsSpec ));
-
- InitFile();
- }
-
-
- /*-------------------------------*** DESTRUCTOR ***----------------------------------*/
-
- ZFile::~ZFile()
- {
- Close();
- CloseResFork();
- }
-
-
- /*---------------------------------*** INITFILE ***----------------------------------*/
- /*
- common construction
-
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::InitFile()
- {
- refNum = _NOT_OPEN;
- resRefNum = _NOT_OPEN;
- isSafeSave = FALSE;
- itsType = kUnknownType;
-
- ssFSpec = itsSpec;
-
- // if the file already exists, get the file type
- // from the file. If file not found, its type is not yet defined.
-
- FInfo finderInfo;
-
- if( FSpGetFInfo( &itsSpec, &finderInfo ) == noErr )
- itsType = finderInfo.fdType;
-
- GetDateTime((unsigned long*) &qd.randSeed );
- }
-
-
- /*------------------------------------*** OPEN ***-----------------------------------*/
- /*
- Open the file ready for reading or writing
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Open()
- {
- FailOSErr( FSpOpenDF( &itsSpec, fsCurPerm, &refNum ));
- SetMark( 0 );
- }
-
-
- /*----------------------------------*** OPENSAFE ***---------------------------------*/
- /*
- Open the file ready for writing via a safe-save temp file
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::OpenSafe()
- {
- // the file is to opened for a safe save. This creates a temporary file in the same place
- // as the original, but with a name built from part of the original plus a random number.
- // The file is set to be invisible in the Finder. When the file is later closed, the
- // catalogue entries will be swapped and the temp file deleted.
-
- long tfRand;
- Str31 tfName;
-
- ssFSpec = itsSpec;
- tfRand = ((unsigned long) Random() << 16L ) + Random();
-
- NumToString( ABS( tfRand ), tfName );
-
- // use up to the first 10 chars of the true name, then append our random characters
-
- ssFSpec.name[0] = MIN( ssFSpec.name[0], 10 );
- ConcatPStrings( ssFSpec.name, tfName );
-
- // create and open the file
-
- FailOSErr( FSpCreate( &ssFSpec, gAppSignature, 'temp', smSystemScript ));
- FailOSErr( FSpOpenDF( &ssFSpec, fsCurPerm, &refNum ));
- SetMark( 0 );
-
- // set this file invisible
-
- FInfo fi;
-
- FailOSErr( FSpGetFInfo( &ssFSpec, &fi ));
- fi.fdFlags |= fInvisible;
- FailOSErr( FSpSetFInfo( &ssFSpec, &fi ));
-
- isSafeSave = TRUE;
- }
-
-
- /*------------------------------------*** CLOSE ***----------------------------------*/
- /*
- closes the file, if open
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Close()
- {
- if (( refNum != _NOT_OPEN ) &&
- ( refNum != 0 ))
- FailOSErr( FSClose( refNum ));
-
- refNum = _NOT_OPEN;
-
- // if we are closing after a safe-save, swap the files and delete the temp file, AND,
- // if the original file doesn't exist, create it before swapping it.
-
- if( isSafeSave )
- {
- if (! IsReal())
- Create();
-
- FailOSErr( FSpExchangeFiles( &itsSpec, &ssFSpec ));
- FailOSErr( FSpDelete( &ssFSpec ));
-
- isSafeSave = FALSE;
- }
- }
-
-
- /*-----------------------------------*** CREATE ***----------------------------------*/
- /*
- create the file on disk. This does not open it.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Create()
- {
- FailOSErr( FSpCreate( &itsSpec, gAppSignature, itsType, smSystemScript ));
- }
-
-
- /*-----------------------------------*** DISCARD ***---------------------------------*/
- /*
- deletes the file after closing it if necessary
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Discard()
- {
- if (refNum != _NOT_OPEN )
- Close();
-
- FailOSErr( FSpDelete( &itsSpec ));
- }
-
-
- /*------------------------------*** OPENRESFORK ***----------------------------------*/
- /*
- opens the files's resource fork
-
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::OpenResFork()
- {
- if ( isSafeSave )
- resRefNum = FSpOpenResFile( &ssFSpec, fsCurPerm );
- else
- resRefNum = FSpOpenResFile( &itsSpec, fsCurPerm );
- FailOSErr((resRefNum == -1)? fnfErr : noErr );
- }
-
-
- /*-----------------------------*** CLOSERESFORK ***----------------------------------*/
- /*
- Closes the resource fork, if open
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::CloseResFork()
- {
- if ( resRefNum != _NOT_OPEN )
- {
- CloseResFile( resRefNum );
- FailOSErr( ResError() );
- }
- resRefNum = _NOT_OPEN;
- }
-
-
- /*----------------------------*** CREATERESFORK ***----------------------------------*/
- /*
- Creates the resource fork, but does not open it
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::CreateResFork()
- {
- if ( isSafeSave )
- FSpCreateResFile( &ssFSpec, gAppSignature, itsType, smSystemScript );
- else
- FSpCreateResFile( &itsSpec, gAppSignature, itsType, smSystemScript );
- FailOSErr( ResError());
- }
-
-
- /*----------------------------------*** READ ***-------------------------------------*/
- /*
- Read some data (<howMuch> bytes, from current mark) from the file into a buffer
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Read( Ptr inBuffer, long* howMuch )
- {
- FailOSErr( isSafeSave? permErr : noErr );
- FailOSErr( FSRead( refNum, howMuch, inBuffer ));
- }
-
- /*---------------------------------*** WRITE ***-------------------------------------*/
- /*
- Write data from the buffer to the file, <howMuch> bytes written from current mark.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Write( Ptr outBuffer, long* howMuch )
- {
- FailOSErr( FSWrite( refNum, howMuch, outBuffer ));
- }
-
-
- /*---------------------------------*** READ ***--------------------------------------*/
- /*
- Reads the entire file into a Handle. The handle is resized initially to the size of the
- file. This technique is unsuitable for large files.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Read( Handle aHandle )
- {
- long howMuch;
- char hs;
-
- FailNIL( aHandle );
- FailOSErr( isSafeSave? permErr : noErr );
-
- // the handle is sized to the size of the rest of the data in the file, that is, the
- // length less the current position. Override this for different behaviour.
-
- howMuch = GetLength() - GetMark();
- SetHandleSize( aHandle, howMuch );
-
- FailOSErr( MemError());
-
- hs = HGetState( aHandle );
- HLock( aHandle );
- Read( *aHandle, &howMuch );
- HSetState( aHandle, hs );
- }
-
-
- /*---------------------------------*** WRITE ***-------------------------------------*/
- /*
- Writes a handle to the file from the current mark.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::Write( Handle aHandle )
- {
- long howMuch;
- char hs;
-
- FailNIL( aHandle );
-
- howMuch = GetHandleSize( aHandle );
-
- hs = HGetState( aHandle );
- HLock( aHandle );
- Write( *aHandle, &howMuch );
- HSetState( aHandle, hs );
-
- // set the length of the file to the current mark, in case the file was
- // shortened. This is OK even if multiple calls are made to this method.
-
- SetLength( GetMark());
- }
-
-
- /*---------------------------------*** SETMARK ***-----------------------------------*/
- /*
- move the file's mark to the absolute position <aMark>. Mark is set to 0 on Open.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::SetMark( const long aMark )
- {
- FailOSErr( SetFPos( refNum, fsFromStart, aMark ));
- }
-
- /*--------------------------------*** SETTYPE ***------------------------------------*/
- /*
- set the type of the file as used in subsequent Create() calls, or if the file already
- exists, this changes the file's type on disk. Use with care, since the content of a file
- may be totally invalidated by this call.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::SetType( const OSType aType )
- {
- if (aType != itsType)
- {
- itsType = aType;
-
- if ( IsReal())
- {
- FInfo fi;
-
- FailOSErr( FSpGetFInfo( &itsSpec, &fi ));
- fi.fdType = itsType;
- FailOSErr( FSpSetFInfo( &itsSpec, &fi ));
- }
- }
- }
-
-
- /*--------------------------------*** GETMARK ***--------------=---------------------*/
- /*
- Get the current position of the file
- ---------------------------------------------------------------------------------------*/
-
- long ZFile::GetMark()
- {
- long mark = 0;
-
- FailOSErr( GetFPos( refNum, &mark ));
-
- return mark;
- }
-
- /*--------------------------------*** GETFSSPEC ***----------------------------------*/
- /*
- get the file specification record of the file. You can get the name from this.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::GetFSSpec( FSSpec* aSpec )
- {
- *aSpec = itsSpec;
- }
-
-
- /*-------------------------------*** SETRESFORK ***----------------------------------*/
- /*
- sets the resfork of this file to be the current resource file, and returns the one set
- originally. This will only work if the res fork exists and is open.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::SetResFork(short* curRes)
- {
- *curRes = CurResFile();
-
- if ( resRefNum != _NOT_OPEN )
- UseResFile( resRefNum );
- }
-
-
- /*-------------------------------*** GETLENGTH ***-----------------------------------*/
- /*
- Get the length of the file.
- ---------------------------------------------------------------------------------------*/
-
- long ZFile::GetLength()
- {
- long len = 0;
-
- FailOSErr( GetEOF( refNum, &len ));
-
- return len;
- }
-
-
- /*--------------------------------*** SETLENGTH ***----------------------------------*/
- /*
- set the length of the file. You should call this after updating a file in case it got
- shorter. Write() with a handle argument does this automatically.
- ---------------------------------------------------------------------------------------*/
-
- void ZFile::SetLength( const long aLength )
- {
- FailOSErr( SetEOF( refNum, aLength ));
- }
-
-
- /*--------------------------------*** GETTYPE ***------------------------------------*/
- /*
- get the file's type
- ---------------------------------------------------------------------------------------*/
-
- OSType ZFile::GetType()
- {
- return itsType;
- }
-
- /*-----------------------------*** HASRESFORK ***------------------------------------*/
- /*
- does this file have a resource fork? (n.b. if file not created yet, returns false)
- ---------------------------------------------------------------------------------------*/
-
- Boolean ZFile::HasResFork()
- {
- Str31 fName;
- CInfoPBRec pb;
- OSErr theErr;
-
- if ( isSafeSave )
- CopyPString( ssFSpec.name, fName );
- else
- CopyPString( itsSpec.name, fName );
-
- pb.hFileInfo.ioCompletion = NULL;
- pb.hFileInfo.ioNamePtr = fName;
- pb.hFileInfo.ioVRefNum = itsSpec.vRefNum;
- pb.hFileInfo.ioDirID = itsSpec.parID;
- pb.hFileInfo.ioFDirIndex = 0;
-
- theErr = PBGetCatInfoSync( &pb );
-
- if (theErr)
- return FALSE;
- else
- {
- // see if any physical bytes are alloted to the resource fork
-
- return( pb.hFileInfo.ioFlRPyLen > 0 );
- }
- }
-
-
- /*-----------------------------*** HASDATAFORK ***-----------------------------------*/
- /*
- does this file have a data fork? (n.b. if file not created yet, returns false)
- ---------------------------------------------------------------------------------------*/
-
- Boolean ZFile::HasDataFork()
- {
- Str31 fName;
- CInfoPBRec pb;
- OSErr theErr;
-
- if ( isSafeSave )
- CopyPString( ssFSpec.name, fName );
- else
- CopyPString( itsSpec.name, fName );
-
- pb.hFileInfo.ioCompletion = NULL;
- pb.hFileInfo.ioNamePtr = fName;
- pb.hFileInfo.ioVRefNum = itsSpec.vRefNum;
- pb.hFileInfo.ioDirID = itsSpec.parID;
- pb.hFileInfo.ioFDirIndex = 0;
-
- theErr = PBGetCatInfoSync( &pb );
-
- if (theErr)
- return FALSE;
- else
- {
- // see if any physical bytes are alloted to the data fork
-
- return( pb.hFileInfo.ioFlPyLen > 0 );
- }
- }
-
-
- /*--------------------------------*** ISREAL ***-------------------------------------*/
- /*
- does this file exist on the physical diskdrive (or network volume)?
- ---------------------------------------------------------------------------------------*/
-
- Boolean ZFile::IsReal()
- {
- OSErr theErr;
- FInfo fi;
-
- theErr = FSpGetFInfo( &itsSpec, &fi );
- return (theErr == noErr);
- }
-
-
- /*-------------------------------*** ISLOCKED ***------------------------------------*/
- /*
- is this file locked?
- ---------------------------------------------------------------------------------------*/
-
- Boolean ZFile::IsLocked()
- {
- OSErr theErr;
- FInfo fi;
-
- theErr = FSpGetFInfo( &itsSpec, &fi );
- return (( theErr == noErr ) &&
- ( fi.fdFlags & 0x1000 ));
- }
-
-
- /*---------------------------------*** ISOPEN ***------------------------------------*/
- /*
- is this file currently open?
- ---------------------------------------------------------------------------------------*/
-
- Boolean ZFile::IsOpen()
- {
- return ( refNum != _NOT_OPEN );
- }
-
-